#include "TreeBuilder.h"
#include "LTree.h"
#include "RandomUtil.h"
#include "Terrain.h"

std::list<WorldObject*> TreeBuilder::getTrees(float minx, float maxx, float minz, float maxz, unsigned int saturation, unsigned int seed) {
	if(minx > maxx || minz > maxz) {
		throw "Invalid arguments. Minimum values cannot be greater than maximum values.";
	}

	std::list<WorldObject*> ret = std::list<WorldObject*>();

	for(float x = minx; x <= maxx; x += 5.0) {
		for(float z = minz; z < maxz; z += 5.0) {
			int val = RandomUtil::random(0, saturation, hash(x, z, seed));
			if (val < 1) {
				ret.push_back(createTree(x, Terrain::getHeight(x,z), z, RandomUtil::random(0, 30)));
			}
		}
	}
	

	return ret;
}

unsigned int TreeBuilder::hash(float x, float z, unsigned int seed) {
	return (*(unsigned int *)&x) ^ ((*(unsigned int *)&z) << 8) / (seed + 1) << 2;
}

LGrammar* TreeBuilder::getRandomGrammar(void) {
	static LGrammar* grammar = 0;
	if(grammar == 0) {
		grammar = new LGrammar();
		grammar->setStartString("T");

		LGrammarRule *tree = new LGrammarRule('T', "cB");
		LGrammarRule *branches = new LGrammarRule('B', "bB", 3);
			branches->addProductionRule("b", 1);
		LGrammarRule *segment = new LGrammarRule('S', "McB[L]", 3);
	//		segment->addProductionRule("MLS", 2);
	//		segment->addProductionRule("B",1);
		LGrammarRule *branch = new LGrammarRule('b', "[S]", 1);
		LGrammarRule *modifiers = new LGrammarRule('M', "YZ");
		LGrammarRule *ymods = new LGrammarRule('Y', "Yy", 2);
			ymods->addProductionRule("y", 1);
		LGrammarRule *ymod = new LGrammarRule('y', "*", 1);
			ymod->addProductionRule("/",1);
		LGrammarRule *zmods = new LGrammarRule('Z', "z", 2);
		//	zmods->addProductionRule("z", 1);
		LGrammarRule *zmod = new LGrammarRule('z', "+", 1);
			zmod->addProductionRule("-",1);	

		grammar->addRule(tree);
		grammar->addRule(segment);
		grammar->addRule(branches);
		grammar->addRule(branch);
		grammar->addRule(modifiers);
		grammar->addRule(ymods);
		grammar->addRule(ymod);
		grammar->addRule(zmods);
		grammar->addRule(zmod);
	}	
	return grammar;
}

LGrammar* TreeBuilder::getRandomGrammar2(void) {
	static LGrammar* grammar = 0;
	if(grammar == 0) {
		grammar = new LGrammar();
		grammar->setStartString("T");

		LGrammarRule *tree = new LGrammarRule('T', "cB");
		LGrammarRule *branches = new LGrammarRule('B', "bB", 3);
			branches->addProductionRule("b", 1);
//		LGrammarRule *segment = new LGrammarRule('S', "McB[L]", 3);
		LGrammarRule *segment = new LGrammarRule('S', "McBP**P**P", 3);
	//		segment->addProductionRule("MLS", 2);
	//		segment->addProductionRule("B",1);
		LGrammarRule *branch = new LGrammarRule('b', "[S]", 1);
		LGrammarRule *modifiers = new LGrammarRule('M', "YZ");
		LGrammarRule *ymods = new LGrammarRule('Y', "Yy", 2);
			ymods->addProductionRule("y", 1);
		LGrammarRule *ymod = new LGrammarRule('y', "*", 1);
			ymod->addProductionRule("/",1);
		LGrammarRule *zmods = new LGrammarRule('Z', "zZ", 1);
			zmods->addProductionRule("z", 3);
		LGrammarRule *zmod = new LGrammarRule('z', "+", 1);
			zmod->addProductionRule("-",1);	

		grammar->addRule(tree);
		grammar->addRule(segment);
		grammar->addRule(branches);
		grammar->addRule(branch);
		grammar->addRule(modifiers);
		grammar->addRule(ymods);
		grammar->addRule(ymod);
		grammar->addRule(zmods);
		grammar->addRule(zmod);
	}	
	return grammar;
}

LGrammar* TreeBuilder::getSymmetricGrammar(void) {
	static LGrammar* grammar = 0;
	if(grammar == 0) {
		grammar = new LGrammar();
		grammar->setStartString("T");
		grammar->addRule(new LGrammarRule('T', "T[+TP][**-TP][/-TP]"));
	}
	return grammar;
}

LGrammar* TreeBuilder::getWeirdGrammar(void) {
	static LGrammar* grammar = 0;
	if(grammar == 0) {
		grammar = new LGrammar();
		grammar->setStartString("T");
		grammar->addRule(new LGrammarRule('T', "TT**-[-T+T+TP**P**P]*+[T-T-TP**P**P]"));
	}
	return grammar;
}

LGrammar* TreeBuilder::getFlowerGrammar(void) {
	static LGrammar* grammar = 0;
	if(grammar == 0) {
		grammar = new LGrammar();
		grammar->setStartString("F");

		LGrammarRule *flower = new LGrammarRule('F', "Sp");
		LGrammarRule *petal = new LGrammarRule('p', "[+***P]*p");

		grammar->addRule(flower);
		grammar->addRule(petal);

	}
	return grammar;
}

WorldObject* TreeBuilder::createTree(float x, float y, float z, int type) {
	LTree *ltree;
	unsigned int tmp = RandomUtil::random(0, 20);
	if(type < 2) {
			ltree = new LTree(getSymmetricGrammar(),
				RandomUtil::random(15, 40),
				Location(x, y, z),
				RandomUtil::random(2, 3));
	} else {
			ltree = new LTree(getRandomGrammar(),
				RandomUtil::random(15, 40),
				Location(x, y, z),
				RandomUtil::random(7,9));
	}


	ltree->generateTree(); //to make sure the tree is generated with the right rand seed.
	return ltree;
}
